Procedures and Scopes
Table of Contents
1. Default Parameters and Named Arguments
We can give default value to parameters.
// b has default value 1, its type is inferred
// c has default value "hello", and has type string
my_proc :: proc(a: int, b := 1, c: string = "hello") {}
// we can call with labels
my_proc(
a = 7,
c = "Yes",
)
my_proc(
7, // a = 7, b is still default
c = "Yes",
)
Note, parameters are immutable. To modify parameters, we can create a copy of parameter and assign it to a variable with same name.
div :: proc(n: f32, d: f32) -> f32 {
n := n // this line
n = n / d
return n
}
To modify the data, we can pass as pointer.
1.1. Immutable Reference By Default
Note: A parameter that is larger than 16 bytes will automatically be passed as an immutable reference.
2. Multiple Return Values
Return as a tuple.
swap :: proc(n: int, m: int) -> (int, int) {
return m, n
}
By default, return values can be ignored. If you want to force users to handle return values, we can add result-requiring tags.
@require_results
swap :: proc(n: int, m: int) -> (int, int) {
return m, n
}
3. Named Return Values
We can give names to return values, they act like normal variables pre-declared.
div :: proc(n: f32, d: f32) -> (res: f32, ok: bool) {
if d == 0 {
return
}
res = (n / d)
ok = true
return
}
4. Nested Procedures and Captured Variables
We can declare a procedure within a procedure. Such procedures can use global variables and constants, but not variables declared locally in parental procedure.
4.1. Static Variables within Procedures
We can declare static variables within procedures with @static tag.
@static my_var: int
A static variable bahaves like a global variable, but it’s only accessible within the procedure where it’s declared, as well as any nested procedures. Its value persists among different calls to this procedure.
5. Explicit Overloading
We can use explicit overloading to make 2 or more procedures exist under the same name. Note in the following example how length procedure is declared
length :: proc {
length_float2,
length_float3,
}
length_float2 :: proc(v: [2]f32) -> f32 {
return math.sqrt(v.x * v.x + v.y * v.y)
}
length_float3 :: proc(v: [3]f32) -> f32 {
return math.sqrt(v.x*v.x + v.y*v.y + v.z*v.z)
}
6. Run Procedures at Startup and Shutdown
Put @init before the startup procedure and @fini before ending procedure.
import "core:fmt"
main :: proc() { fmt.println("Program running") }
@init
startup :: proc() { fmt.println("Program started") }
@fini
shutdown :: proc() { fmt.println("Program shutting down") }
// Will print
// Program started
// Program running
// Program shutting down